use std::{collections::HashMap, fs, io::Read, path::PathBuf, sync::Mutex};

use serde::{Deserialize, Serialize};
use tauri::{App, AppHandle, Manager, State};
use tauri_plugin_global_shortcut::Shortcut;

use crate::{save_to_file, shortcut_manage, types::TResult};

#[derive(Deserialize, Serialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct AppConfig {
    pub local_hotkey: Option<String>,
    pub local_screen_target: Option<String>,
    pub remote_hotkey: Option<String>,
    pub save_type_list: Option<Vec<String>>,
    pub save_path: Option<String>,
    pub remote_address: Option<String>,
    pub auto_create_save_path: Option<bool>,
    pub img_save_type: Option<String>,
}

impl AppConfig {
    pub fn save_to_file(&self, file_path: &str) -> TResult<()> {
        let buf = toml::to_string(self)?;
        save_to_file::save_bytes_to_file(file_path, buf.as_bytes(), true)
    }
}

pub struct Storage {
    pub app_config: Mutex<AppConfig>,
    pub shortcut_map: Mutex<HashMap<Shortcut, fn(app_handle: &AppHandle) -> TResult<()>>>,
}

pub fn get_config_file_path(app_handle: &AppHandle) -> TResult<PathBuf> {
    let mut app_config_dir = app_handle
        .path()
        .app_config_dir()
        .map_err(|_| "获取应用路径失败")?;
    app_config_dir.push("config.toml");
    Ok(app_config_dir)
}

fn get_config_from_file(path: &PathBuf) -> TResult<AppConfig> {
    let mut file = fs::File::open(path)?;
    let mut content: String = String::from("");
    file.read_to_string(&mut content)?;
    Ok(toml::from_str(&content)?)
}

pub fn init(app: &mut App) -> TResult<()> {
    let config_file_path = get_config_file_path(app.app_handle())?;
    println!("config_file_path: {:?}", config_file_path);

    let state: State<Storage> = app.state();
    let mut app_config = state
        .app_config
        .lock()
        .map_err(|_| "锁定 app_config 失败")?;

    let config = match get_config_from_file(&config_file_path) {
        Ok(config) => config,
        _ => app_config.clone(),
    };

    *app_config = config.clone();

    shortcut_manage::init(app.app_handle(), &config).map_err(|_| "注册快捷键失败")?;
    config.save_to_file(config_file_path.to_str().ok_or("配置文件路径转换失败")?)?;

    Ok(())
}
